package xyz.zcq.zcqrpc.server.tcp;

import io.vertx.core.Handler;
import io.vertx.core.net.NetSocket;
import xyz.zcq.zcqrpc.model.RpcRequest;
import xyz.zcq.zcqrpc.model.RpcResponse;
import xyz.zcq.zcqrpc.protocol.ProtocolMessage;
import xyz.zcq.zcqrpc.protocol.ProtocolMessageDecoder;
import xyz.zcq.zcqrpc.protocol.ProtocolMessageEncoder;
import xyz.zcq.zcqrpc.protocol.ProtocolMessageTypeEnum;
import xyz.zcq.zcqrpc.registry.LocalImplRegistry;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * TCP请求处理
 */
public class TcpServerHandler implements Handler<NetSocket> {

    @Override
    public void handle(NetSocket netSocket) {
        TcpBufferHandlerWrapper tcpBufferHandlerWrapper = new TcpBufferHandlerWrapper(buffer -> {
            // 解码
            ProtocolMessage<RpcRequest> reqPm;
            try {
                reqPm = (ProtocolMessage<RpcRequest>) ProtocolMessageDecoder.decode(buffer);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            RpcRequest rpcRequest = reqPm.getBody();

            // 处理请求
            RpcResponse rpcResponse = new RpcResponse();
            Class<?> implClass = LocalImplRegistry.get(rpcRequest.getServiceName());
            try {
                Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(implClass.newInstance(), rpcRequest.getParameters());
                rpcResponse.setData(result);
                rpcResponse.setMessage("ok");
                rpcResponse.setDataType(method.getReturnType());
            } catch (Exception e) {
                e.printStackTrace();
                rpcResponse.setMessage(e.getMessage());
                rpcResponse.setException(e);
            }
            ProtocolMessage.Header header = reqPm.getHeader();
            header.setType((byte) ProtocolMessageTypeEnum.RESPONSE.getKey());
            ProtocolMessage<RpcResponse> resPm = new ProtocolMessage<>(header, rpcResponse);
            try {
                netSocket.write(ProtocolMessageEncoder.encode(resPm));
            } catch (IOException e) {
                throw new RuntimeException("协议消息编码错误");
            }
        });
        netSocket.handler(tcpBufferHandlerWrapper);
    }

}
